#include "EVENTHANDLER.H"
#include "EventScheme.h"
#include "ORACLEADAPTER.h"
#include "MetaXmlHandler.h"
#include <list>
#include "comtools.h"

EventHandler::EventHandler()
: MetaStorageBase()
{
}

EventHandler::~EventHandler()
{
}

void EventHandler::saveObject(MessageQueueObject * obj)
{
  EventScheme * pObj = dynamic_cast<EventScheme*>(obj);
  if (NULL == pObj) return;
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  ADODB::_RecordsetPtr rs;  
  rs.CreateInstance (__uuidof(ADODB::Recordset));  
  rs->Open(L"EVENT_SCHEME", _variant_t(pAdapt->getConnecion(), false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdTable);  

  rs->AddNew();
  rs->Fields->GetItem(L"message_id")->Value = pObj->getMessageId();
  rs->Fields->GetItem(L"executable")->Value = pObj->getExecutable();
  rs->Fields->GetItem(L"event_name")->Value = pObj->getEventName();
  rs->Fields->GetItem(L"event_type")->Value = pObj->getEventType();
  rs->Fields->GetItem(L"event_severity")->Value = pObj->getEventSeverity();
  rs->Fields->GetItem(L"event_category")->Value = pObj->getCategory();
  rs->Fields->GetItem(L"seq_name")->Value = pObj->getSeqName();
  rs->Fields->GetItem(L"seq_number")->Value = pObj->getSequence();
  rs->Fields->GetItem(L"seq_size")->Value = pObj->getSequenceSize();
  rs->Fields->GetItem(L"method_name")->Value = pObj->getMethodName();
  rs->Fields->GetItem(L"direction_type")->Value = pObj->getDirection();
  rs->Update();

  try { rs->Close(); } catch (...) {}
}

std::list<MessageQueueObject*>& EventHandler::search(const char* pszExec, const char* pszClassName, const char* pszMethodName, std::list<MessageQueueObject*>& list)
{
  list.clear();

  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return list;

  HRESULT hr = S_FALSE;

  _bstr_t sql = " select * from event_pattern where executable = '"+ _bstr_t(pszExec) +"' and class_name = '"+ _bstr_t(pszClassName) +"' and method_name = '"+ _bstr_t(pszMethodName) +"' order by seq_number ";

  ADODB::_RecordsetPtr rs;  
  rs.CreateInstance (__uuidof(ADODB::Recordset));  
  rs->Open(sql, _variant_t(pAdapt->getConnecion(), false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  

  _bstr_t exec, name, type, pattern, severity, seqname;
  long seq, seqsize;

  if (!rs->ADOEOF) hr = rs->MoveFirst();
  while (S_OK == hr && !rs->ADOEOF) {
    exec = _bstr_t(rs->Fields->GetItem(L"executable")->GetValue());
    name = _bstr_t(rs->Fields->GetItem(L"event_name")->GetValue());
    severity = _bstr_t(rs->Fields->GetItem(L"event_severity")->GetValue());
    type = _bstr_t(rs->Fields->GetItem(L"event_type")->GetValue());
    
    seq = (long)rs->Fields->GetItem(L"seq_number")->GetValue();
    seqsize = (long)rs->Fields->GetItem(L"seq_size")->GetValue();
    pattern = _bstr_t(rs->Fields->GetItem(L"method_name")->GetValue());
    seqname = _bstr_t(rs->Fields->GetItem(L"seq_name")->GetValue());
    
    EventScheme * pEvent = new EventScheme;
    pEvent->setClassName(pszClassName);
    pEvent->setMethodName(pszMethodName);
    pEvent->setExecutable(exec);
    if (_bstr_t("") != exec && _bstr_t("") != name)       
      if (S_OK == hr) (pEvent)->setMetadata(name, type, severity, seqname, seq, seqsize);
    
    list.push_back(pEvent);

    hr = rs->MoveNext();
  } 

  try { rs->Close(); } catch (...) {}

  return list;
}

long EventHandler::SequenceCount(EventScheme * pEventSch)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return 0;

  long retval = 0;
  try {
    HRESULT hr;

    _bstr_t sql = " select distinct seq_number "
                  " from event_scheme "
                  " where executable = '"+_bstr_t(pEventSch->getExecutable())+"' " 
                  " and event_name = '"+_bstr_t(pEventSch->getEventName())+"' "
                  " and seq_name = '"+_bstr_t(pEventSch->getSeqName())+"' "
                  " and eventscheme_status = 0 \n";

    ::OutputDebugString(sql);

    ADODB::_RecordsetPtr rs;  
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(), false), ADODB::adOpenStatic, ADODB::adLockOptimistic, ADODB::adCmdText);  

    retval = rs->RecordCount;

    try { rs->Close(); } catch (...) {}
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
  return retval;
}

void EventHandler::SearchEventMetaData(const char* matchExec, const char* matchClass, const char* matchMethod, EventScheme ** ppEvent)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  HRESULT hr;

  _bstr_t sql = " select * "
                " from event_pattern "
                " where executable = '"+ _bstr_t(matchExec) +"' "
                " and method_name = '"+ _bstr_t(matchMethod) +"' "
                " and class_name = '"+ _bstr_t(matchClass) +"' ";

  ADODB::_RecordsetPtr rs;  
  rs.CreateInstance (__uuidof(ADODB::Recordset));  
  hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(), false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  

  _bstr_t exec, name, type, pattern, severity, seqname, category;
  long seq, seqsize;

  if (!rs->ADOEOF) hr = rs->MoveFirst();
  if (S_OK == hr && !rs->ADOEOF) {
    exec = _bstr_t(rs->Fields->GetItem(L"executable")->GetValue());
    name = _bstr_t(rs->Fields->GetItem(L"event_name")->GetValue());
    severity = _bstr_t(rs->Fields->GetItem(L"event_severity")->GetValue());
    category = _bstr_t(rs->Fields->GetItem(L"event_category")->GetValue());
    type = _bstr_t("EVENT"); 
    
    seq = (long)rs->Fields->GetItem(L"seq_number")->GetValue();
    seqsize = (long)rs->Fields->GetItem(L"seq_size")->GetValue();
    pattern = _bstr_t(rs->Fields->GetItem(L"method_name")->GetValue());
    seqname = _bstr_t(rs->Fields->GetItem(L"seq_name")->GetValue());
    
    if (NULL == *ppEvent) *ppEvent = new EventScheme;
    if (_bstr_t("") != exec && _bstr_t("") != name) {            
      (*ppEvent)->setMetadata(name, type, severity, seqname, seq, seqsize);
      (*ppEvent)->setCategory(category);
    }
  } 

  try { rs->Close(); } catch (...) {}
}

void EventHandler::SelectFullPattern(EventScheme ** ppEventSch)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  try {
    _bstr_t sql =  " select isnull(class_name, ' ') as class_name, method_name, direction_type, seq_number, seq_size "
                   " from event_pattern "
                   " where executable = '"+ _bstr_t((*ppEventSch)->getExecutable()) +"' "
                   " and event_name = '"+ _bstr_t((*ppEventSch)->getEventName()) +"' "
                   " and seq_name = '"+ _bstr_t((*ppEventSch)->getSeqName()) +"' "
                   " order by seq_number \n";

    HRESULT hr;
    ADODB::_RecordsetPtr rs;
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(), false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  

    while (!rs->ADOEOF) {
      _bstr_t classname = (_bstr_t)rs->Fields->GetItem(L"class_name")->GetValue();
      _bstr_t methodname = (_bstr_t)rs->Fields->GetItem(L"method_name")->GetValue();
      _bstr_t direction = (_bstr_t)rs->Fields->GetItem(L"direction_type")->GetValue();
      long seq = (long)rs->Fields->GetItem(L"seq_number")->GetValue();
      long seqsize = (long)rs->Fields->GetItem(L"seq_size")->GetValue();

      std::string s;
      s = "  <class>"+classname+"</class>"
          "  <method>"+methodname+"</method>";
      (*ppEventSch)->addPattern(s);

      rs->MoveNext();
    }

    try { rs->Close(); } catch (...) {}
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void EventHandler::SetEventSchemeStatus(E_STATUS status, EventScheme * pEventSch)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  try {
    HRESULT hr;
    for (int i=1; i<=pEventSch->getSequenceSize(); ++i) 
    {
      _bstr_t sql = " select seq_number, eventscheme_status, eventscheme_id "
                    " from event_scheme "
                    " where executable = '"+_bstr_t(pEventSch->getExecutable())+"' " 
                    " and event_name = '"+_bstr_t(pEventSch->getEventName())+"' "
                    " and seq_name = '"+_bstr_t(pEventSch->getSeqName())+"' " 
                    " and seq_number = '"+_bstr_t(i)+"' "
                    " and EVENTSCHEME_STATUS = 0 "
                    " group by seq_number, eventscheme_status, eventscheme_id\n ";

      ADODB::_RecordsetPtr rs;  
      hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
      hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  
      if (!rs->ADOEOF)  {
        hr = rs->MoveFirst();
        rs->Fields->Item[L"EVENTSCHEME_STATUS"]->Value = _variant_t((int)DELIVERED);
        //rs->Fields->Item[L"REF_MESSAGE_ID"]->Value = _variant_t((int)DELIVERED);
        hr = rs->Update();
      }
      try { rs->Close(); } catch (...) {}
    }
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void EventHandler::SetEventSchemeRefMsgID(long lRefMsg, EventScheme * pEventSch)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;
 
  try {
    long lSeqStep = 1;
    HRESULT hr;

    _bstr_t sql = "select message_id, seq_number, eventscheme_status, ref_message_id "
                  "from event_scheme "
                  "where executable = '"+_bstr_t(pEventSch->getExecutable())+"' "
                  "and event_name = '"+_bstr_t(pEventSch->getEventName())+"' "
                  "and seq_name = '"+_bstr_t(pEventSch->getSeqName())+"' "
                  "and seq_size = "+_bstr_t(pEventSch->getSequenceSize())+" "
                  "and ref_message_id = 0 and eventscheme_status = 1 "
                  "and message_id > 0 "
                  "order by seq_number \n";

    ::OutputDebugString(sql);

    ADODB::_RecordsetPtr rs;  
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenStatic, ADODB::adLockOptimistic, ADODB::adCmdText);  
    if (!rs->ADOEOF) hr = rs->MoveFirst();
    while (!rs->ADOEOF && S_OK == hr) {
      long lCurrSeqNo = rs->Fields->Item[L"SEQ_NUMBER"]->Value;
      if (lSeqStep == lCurrSeqNo) { 
        rs->Fields->Item[L"REF_MESSAGE_ID"]->Value = lRefMsg;
        rs->Fields->Item[L"EVENTSCHEME_STATUS"]->Value = (int)ACKNOWLEDGED; 
        
        hr = rs->Update();
        
        lSeqStep++;
      }      
      if (lSeqStep > pEventSch->getSequenceSize()) break;
      hr = rs->MoveNext();
    }
    
    try { rs->Close(); } catch (...) {}
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void EventHandler::SelectFullTrace(EventScheme ** ppEventSch)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  try {
    HRESULT hr;
    long lSeqSize = (*ppEventSch)->getSequenceSize();
    for (int i=1; i<=lSeqSize; ++i) {
      _bstr_t sql = " select top 1 isnull(class_name, ' ') as class_name, method_name, event_severity, seq_number, seq_size, direction_type, isnull(filename, ' ') as filename, isnull(linenumber, 0) as linenumber, process_id, thread_id "
                    " from event_scheme "
                    " where executable = '"+ _bstr_t((*ppEventSch)->getExecutable()) +"' "
                    " and event_name = '"+ _bstr_t((*ppEventSch)->getEventName()) +"' "
                    " and seq_name = '"+ _bstr_t((*ppEventSch)->getSeqName()) +"' "
                    " and seq_number = '"+ _bstr_t(i) +"' "
                    " order by eventscheme_date desc \n";

      OutputDebugString(sql);

      ADODB::_RecordsetPtr rs;
      hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
      hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  
      if (!rs->ADOEOF) {
        _bstr_t classname = rs->Fields->Item[L"CLASS_NAME"]->GetValue();
        _bstr_t methodname = rs->Fields->Item[L"METHOD_NAME"]->GetValue();
        _bstr_t direction = rs->Fields->Item[L"DIRECTION_TYPE"]->GetValue();
        _bstr_t filename = rs->Fields->Item[L"FILENAME"]->GetValue();
        long lineno = (long)rs->Fields->Item[L"LINENUMBER"]->GetValue();
        long seq = (long)rs->Fields->Item[L"SEQ_NUMBER"]->GetValue();
        long seqsize = (long)rs->Fields->Item[L"SEQ_SIZE"]->GetValue();
        long lprocid = (long)rs->Fields->Item[L"PROCESS_ID"]->GetValue();
        long lthreid = (long)rs->Fields->Item[L"THREAD_ID"]->GetValue();

        _bstr_t trace = "<trace>"
                        "  <component>"
                        "    <filename>"+filename+"</filename>"
                        "    <lineno>"+_bstr_t(lineno)+"</lineno>"
                        "    <executable>"+_bstr_t((*ppEventSch)->getExecutable())+"</executable>"
                        "    <processid>"+_bstr_t(lprocid)+"</processid>"
                        "    <threadid>"+_bstr_t(lthreid)+"</threadid>"
                        "  </component>"
                        "  <object>"
                        "    <class>"+classname+"</class>"
                        "    <method event=\""+direction+"\">"+methodname+"</method>"
                        "  </object>"
                        "</trace>";

        (*ppEventSch)->addTrace(std::string(trace));
      }
      try { rs->Close(); } catch (...) {}
    }
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void EventHandler::SelectTracesByEventId(long lRefMSgID, char ** ppXmlTraces)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  try {
    if (NULL != *ppXmlTraces) return;

    _bstr_t xmlRoot = _bstr_t("<traces></traces>");

    HRESULT hr = S_FALSE;
    VARIANT_BOOL b;
    IXMLDOMDocumentPtr pXMLDOMDoc, pXMLDOMDocTrace; 
    IXMLDOMNodePtr pXMLDOMNode = NULL, pXMLDOMNode2 = NULL, pXMLDOMNodeTrace = NULL, pXMLDOMNodeTraces = NULL, pXMLDOMNodeOuter = NULL;
    IXMLDOMNodeListPtr pXMLDOMNodeList = NULL;
    pXMLDOMDoc.CreateInstance(__uuidof(DOMDocument));
    pXMLDOMDoc->put_async(false);
    pXMLDOMDoc->put_resolveExternals(false);
    pXMLDOMDoc->AddRef();
    hr = pXMLDOMDoc->loadXML(xmlRoot, &b);

    if (S_OK == hr) hr = pXMLDOMDoc->selectSingleNode(_bstr_t("//traces"), &pXMLDOMNode);

    _bstr_t sql = "select q.*, datalength(q.message) * 2 as datasize from message_queue q, event_scheme e where q.message_id = e.message_id and q.status = 1 and e.eventscheme_status = 2 and e.ref_message_id = "+_bstr_t(lRefMSgID)+"\n";    

    ADODB::_RecordsetPtr rs;  
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenStatic, ADODB::adLockOptimistic, ADODB::adCmdText);  
    if (!rs->ADOEOF) hr = rs->MoveFirst();
    while (!rs->ADOEOF && S_OK == hr) {
      _bstr_t msgid = (_bstr_t)rs->Fields->Item[L"MESSAGE_ID"]->Value;
      _bstr_t created = (_bstr_t)rs->Fields->Item[L"CREATED_TIME"]->Value;
      _bstr_t sender = (_bstr_t)rs->Fields->Item[L"SENDER"]->Value;
      _bstr_t status = (_bstr_t)rs->Fields->Item[L"STATUS"]->Value;
      _bstr_t subject = (_bstr_t)rs->Fields->Item[L"SUBJECT"]->Value;

      long datasize = (long)rs->Fields->Item[L"DATASIZE"]->Value;

      _variant_t val;
      BSTR bdataxml, xml = _bstr_t("");

      VariantInit(&val);
      val = rs->Fields->GetItem(L"MESSAGE")->GetChunk(datasize +2);
      COMTools::UnpackVariant(val, &bdataxml);
      VariantClear(&val);

      VARIANT_BOOL bTrace;
      pXMLDOMDocTrace.CreateInstance(__uuidof(DOMDocument));
      pXMLDOMDocTrace->put_async(false);
      pXMLDOMDocTrace->put_resolveExternals(false);
      hr = pXMLDOMDocTrace->loadXML(bdataxml, &bTrace);

      if (S_OK == hr) hr = pXMLDOMDocTrace->selectNodes(_bstr_t("//trace"), &pXMLDOMNodeList);
      if (S_OK == hr) hr = pXMLDOMNodeList->get_item(0, &pXMLDOMNodeTrace);
      if (S_OK == hr) hr = pXMLDOMNode->appendChild(pXMLDOMNodeTrace, &pXMLDOMNodeOuter);

      pXMLDOMNodeTrace = NULL;
      pXMLDOMNodeList = NULL;
      pXMLDOMDocTrace = NULL;

      rs->Fields->Item[L"STATUS"]->Value = (int)ACKNOWLEDGED;
      
      hr = rs->Update();        
      hr = rs->MoveNext();
    }
    try { rs->Close(); } catch (...) {}

    BSTR xml;
    hr = pXMLDOMNode->get_xml(&xml);
    if (S_OK == hr) {
      (*ppXmlTraces) = new char[strlen((char*)_bstr_t(xml))+1];
      memset(*ppXmlTraces, 0, strlen((char*)_bstr_t(xml))+1);
      strncpy(*ppXmlTraces, (char*)_bstr_t(xml), strlen((char*)_bstr_t(xml)));
    }
    ::SysFreeString(xml);
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void EventHandler::StoreEventScheme(EventScheme * pEvent)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  HRESULT hr;
  ADODB::_RecordsetPtr rs;  
  hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
  hr = rs->Open(L"EVENT_SCHEME", _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdTable);  

  rs->AddNew();
  rs->Fields->GetItem(L"message_id")->Value = pEvent->getMessageId();
  rs->Fields->GetItem(L"executable")->Value = pEvent->getExecutable();
  rs->Fields->GetItem(L"event_name")->Value = pEvent->getEventName();
  rs->Fields->GetItem(L"event_type")->Value = pEvent->getEventType();
  rs->Fields->GetItem(L"event_severity")->Value = pEvent->getEventSeverity();
  rs->Fields->GetItem(L"event_category")->Value = pEvent->getCategory();
  rs->Fields->GetItem(L"seq_name")->Value = pEvent->getSeqName();
  rs->Fields->GetItem(L"seq_number")->Value = pEvent->getSequence();
  rs->Fields->GetItem(L"seq_size")->Value = pEvent->getSequenceSize();
  rs->Fields->GetItem(L"class_name")->Value = pEvent->getClassName();
  rs->Fields->GetItem(L"method_name")->Value = pEvent->getMethodName();
  rs->Fields->GetItem(L"direction_type")->Value = pEvent->getDirection();
  rs->Fields->GetItem(L"process_id")->Value = pEvent->getProcessId();
  rs->Fields->GetItem(L"thread_id")->Value = pEvent->getThreadId();
  rs->Fields->GetItem(L"filename")->Value = pEvent->getFileName();
  rs->Fields->GetItem(L"linenumber")->Value = pEvent->getLineNo();
  rs->Update();

  try { rs->Close(); } catch (...) {}
}

void EventHandler::SelectTraceLine(const char* xml, EventScheme ** ppEventSch)
{
  long lMsgID = 0;
  _bstr_t vMethodName, vDirection, vExecutable, vFileName, vLineNo,
          vMsgID, vClassName, vProcessId, vThreadId, vCat;

  MetaXmlHandler xmlhnd(xml);
  vMsgID = xmlhnd.getNodeValue("//message/header/id");
  vExecutable = xmlhnd.getNodeValue("//executable");
  vClassName = xmlhnd.getNodeValue("//class");
  vMethodName = xmlhnd.getNodeValue("//method");
  vDirection = xmlhnd.getAttrValue("//method", "event");
  vProcessId = xmlhnd.getNodeValue("//processid");
  vThreadId = xmlhnd.getNodeValue("//threadid");
  vFileName = xmlhnd.getNodeValue("//filename");
  vLineNo = xmlhnd.getNodeValue("//lineno");
  vCat = xmlhnd.getNodeValue("//category");

  if (NULL == *ppEventSch) *ppEventSch = new EventScheme;

  (*ppEventSch)->setMessageId(_bstr_t(vMsgID));
  (*ppEventSch)->setClassName(_bstr_t(vClassName));
  (*ppEventSch)->setMethodName(_bstr_t(vMethodName));
  (*ppEventSch)->setDirection(_bstr_t(vDirection));
  (*ppEventSch)->setExecutable(_bstr_t(vExecutable));  
  (*ppEventSch)->setProcessId(atol(vProcessId));
  (*ppEventSch)->setThreadId(atol(vThreadId));
  (*ppEventSch)->setFileName(_bstr_t(vFileName));
  (*ppEventSch)->setLineNo(atol(vLineNo));
  (*ppEventSch)->setCategory(vCat);
}

void EventHandler::EventToEventScheme(const char* eventXml, EventScheme ** ppEventSch)
{
  _bstr_t vExecutable, vEventName, vEventType = "EVENT", vEventSev, vSeqName, vMsgId, vCat;
  long lSeqSize = 0, lSeq = 0;

  MetaXmlHandler xmlhnd(eventXml);
  vMsgId = xmlhnd.getNodeValue("//message/header/id");
  vExecutable = xmlhnd.getNodeValue("//event/executable");
  vEventName = xmlhnd.getNodeValue("//event/name");
  vCat = xmlhnd.getNodeValue("//event/category");
  vEventSev = xmlhnd.getAttrValue("//event", "severity");
  vSeqName = xmlhnd.getAttrValue("//set/sequence", "name");
  lSeqSize = xmlhnd.getNodeCount("//set/sequence[0]/pattern");

  (*ppEventSch) = new EventScheme;
  (*ppEventSch)->setMessageId(vMsgId);
  (*ppEventSch)->setRefMessageId(_bstr_t(vMsgId));
  (*ppEventSch)->setExecutable(_bstr_t(vExecutable));
  (*ppEventSch)->setCategory(_bstr_t(vCat));
  (*ppEventSch)->setMetadata(vEventName, vEventType, vEventSev, vSeqName, lSeq, lSeqSize);
}

void EventHandler::SelectEventTraceLine(const char* eventXml, EventScheme ** ppEventSch)
{
  long lMsgID = 0;
  _bstr_t vMethodName, vDirection, vExecutable, vMsgID, vCat;
  HRESULT hr = S_OK;

  MetaXmlHandler xmlhnd(eventXml);
  vMsgID = xmlhnd.getNodeValue("//message/header/id");
  vExecutable = xmlhnd.getNodeValue("//executable");
  vCat = xmlhnd.getNodeValue("//category");
  vMethodName = xmlhnd.getNodeValue("//method");
  vDirection = xmlhnd.getAttrValue("//method", "event");

  if (NULL == *ppEventSch) *ppEventSch = new EventScheme;
  if (S_OK == hr) {
    (*ppEventSch)->setMethodName(_bstr_t(vMethodName));
    (*ppEventSch)->setDirection(_bstr_t(vDirection));
    (*ppEventSch)->setExecutable(_bstr_t(vExecutable));
    (*ppEventSch)->setMessageId(_bstr_t(vMsgID));
    (*ppEventSch)->setCategory(_bstr_t(vCat));
  }
}